home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gnulib / libsrc98.zoo / spawnve.c < prev    next >
C/C++ Source or Header  |  1993-11-05  |  5KB  |  210 lines

  1. /*
  2.    89/03/02: ERS: added the "mode" argument for MS-DOS/Unix
  3.    compatibility. Added prototypes for GNU C.
  4.  
  5.    fixed spawnve: the original didn't pass the command tail
  6.    correctly, nor did it handle errno right. Also, this version
  7.    passes args in the environment as well as the command line,
  8.    using the ARGV= mechanism supported by crt0.s
  9.  
  10.    Written 89/01/10 by ERS. Original version Copyright (c) 1988 by
  11.    Memorial University of Newfoundland. This version is based upon
  12.    that original, but is substantially different. (In fact, there
  13.    probably isn't a single line of the original left.)
  14. */
  15.  
  16. #include    <stdarg.h>
  17. #include    <process.h>
  18. #include    <param.h>
  19. #include    <errno.h>
  20. #include    <osbind.h>
  21. #include    <stdlib.h>
  22. #include    <time.h>
  23. #include    <string.h>
  24. #include    <fcntl.h>
  25. #include    <unistd.h>
  26. #include    "lib.h"
  27.  
  28. extern char **environ;
  29.  
  30. clock_t _child_runtime;
  31. clock_t _sys_runtime;
  32.  
  33. #define TOS_ARGS 126
  34. static    char    cmd[TOS_ARGS+1];
  35.  
  36. /*
  37.  * FIXME: currently mode == P_OVERLAY doesn't work as advertised, i.e. it
  38.  * doesn't free whatever memory it can.
  39.  */
  40.  
  41. int
  42. spawnve(mode, _path, argv, envp)
  43.     int        mode;
  44.     const char    *_path;
  45.     char * const    *argv;
  46.     char * const    *envp;
  47. {
  48.     void        __exit(long);
  49.     static char    path[MAXPATHLEN];
  50.     size_t        cmlen;
  51.     size_t        enlen = 0;
  52.     char        *p;
  53.     char        *s, *t;
  54.     char        *env;
  55.     clock_t        _child_start;
  56.     long        rval;
  57.  
  58.     if (mode != P_WAIT && mode != P_OVERLAY && mode != P_NOWAIT) {
  59.         errno = EINVAL;
  60.         return -1;
  61.     }
  62.     (void)unx2dos(_path, path);    /* convert filename, if necessary */
  63.     if (!envp)
  64.         envp = environ;
  65.  
  66. /* count up space needed for environment */
  67.     for(cmlen = 0; argv[cmlen]; cmlen++)
  68.         enlen += strlen(argv[cmlen]) + 1;
  69.     for(cmlen = 0; envp[cmlen]; cmlen++)
  70.         enlen += strlen(envp[cmlen]) + 1;
  71.     enlen += 32;    /* filler for stuff like ARGV= and zeros */
  72.  
  73.     if ((env = (char *)Malloc((long)enlen)) == NULL) {
  74.         errno = ENOMEM;
  75.         return -1;
  76.     }
  77.     s = env;
  78.     while ((p = *envp) != 0) {
  79. /*
  80.  * NOTE: in main.c, we converted the PATH environment variable into
  81.  * POSIX form. Here, we convert back into gulam form. Note that the
  82.  * new variable will be shorter than the old, so space is not a problem.
  83.  */
  84.         if (!strncmp(p, "PATH=", 5)) {
  85.             strncpy(s, p, 5); s += 5; p += 5;
  86.             while (*p) {
  87.                 if (!strncmp(p, "/dev/", 5) && p[5]) {
  88.                     *s++ = p[5];
  89.                     *s++ = ':';
  90.                     p += 6;
  91.                 } else if (*p == ':') {
  92.                     *s++ = ','; p++;
  93.                 } else if (*p == '/') {
  94.                     *s++ = '\\'; p++;
  95.                 } else {
  96.                     *s++ = *p++;
  97.                 }
  98.             }
  99.         } else {
  100.             while(*p)
  101.                 *s++ = *p++;
  102.         }
  103.         *s++ = '\0';
  104.         envp++;
  105.     }
  106.     strcpy(s, "ARGV=");
  107.     s += 6; /* s+=sizeof("ARGV=") */
  108.  
  109. /* copy argv[0] first (because it doesn't go into the command line */
  110.     if (argv && *argv) {
  111.         for (p = *argv; *p; )
  112.             *s++ = *p++;
  113.         *s++ = '\0';
  114.     }
  115.  
  116.     bzero(t = cmd, sizeof(cmd));
  117.  
  118. /* s points at the environment's copy of the args */
  119. /* t points at the command line copy to be put in the basepage */
  120.  
  121.     cmlen = 0;        /* was missing -- mmn, 92/03/10 */
  122.     if (argv && *argv) {
  123.         t++;
  124.         while (*++argv) {
  125.             p = *argv;
  126.             while (*p) {
  127.                               if (cmlen <= TOS_ARGS) {
  128.                                       *t++ = *p; cmlen++;
  129.                               }
  130.                 *s++ = *p++;
  131.             }
  132.                         if (cmlen <= TOS_ARGS && *(argv+1)) {
  133.                                 *t++ = ' '; cmlen++;
  134.                         }
  135.                 *s++ = '\0';
  136.         }
  137. /*                *cmd = (char) cmlen;  NOT ANY MORE */
  138.     }
  139.  
  140.     /* tie off environment */
  141.     *s++ = '\0';
  142.     *s = '\0';
  143.  
  144.     /* signal Extended Argument Passing */
  145.     *cmd = 0x7f;
  146.  
  147.     /* close files marked for close on exec */
  148.     for(cmlen = 0; cmlen < __NHANDLES; cmlen++)
  149.         if(__open_stat[cmlen].eclose)
  150.         (void)close(cmlen + __SMALLEST_VALID_HANDLE);
  151.  
  152.     _child_start = clock();
  153.  
  154. /* MiNT and MicroRTX support background processes with Pexec(100,...) */
  155.     cmlen = (mode == P_NOWAIT) ? 100 : PE_LOADGO;
  156.  
  157.     if ((rval = Pexec((int)cmlen, path, cmd, env)) < 0)
  158.     {
  159.         errno = -rval;
  160.         cmlen = -1;
  161.     }
  162.     if (mode == P_OVERLAY)
  163.         __exit(rval);
  164.  
  165.     (void)Mfree(env);
  166.     _child_runtime += (clock() - _child_start);
  167.     return rval;
  168. }
  169.  
  170. int
  171. spawnv(mode, path, argv)
  172.     int         mode;
  173.     const char     *path;
  174.     char * const    *argv;
  175. {
  176.     return spawnve(mode, path, argv, environ);
  177. }
  178.  
  179. #ifdef __STDC__
  180. int spawnle(int mode, const char *path, ...)
  181. #else
  182. int spawnle(mode, path)
  183.     int        mode;
  184.     const char    *path;
  185. #endif
  186. {
  187.     va_list args;
  188.     char    ***envp;
  189.  
  190.     va_start(args, path);
  191.  
  192.     for (envp = (char ***) args ; *envp ; envp++)
  193.         ;
  194.     return spawnve(mode, path, (char **)args, *(envp+1));
  195. }
  196.  
  197. #ifdef __STDC__
  198. int spawnl(int mode, const char *path, ...)
  199. #else
  200. int spawnl(mode, path)
  201.     int        mode;
  202.     const char    *path;
  203. #endif
  204. {
  205.     va_list args;
  206.  
  207.     va_start(args, path);
  208.     return spawnve(mode, path, (char **)args, environ);
  209. }
  210.